window.whevent = {
	// 调试模式下,将由记录器调用打印
	debugMode: false,
	// logger对象用于调试模式,若没有分配,则使用console.log代替
	logger: null,
	// 调用的最后一个事件对象
	lastEvent: null,
	// 回调栈
	_callStacks: {},

	/**
	 * 绑定(事件对象)
	 * @param signal 标志
	 * @param func 回调
	 * @param self 自己
	 */
	bind: function (signal, func, self) {
		if (!this._callStacks[signal]) {
			this._callStacks[signal] = [];
		}
		this._callStacks[signal].push({ func: func, self: self, once: false });
	},

	/**
	 * 优先绑定(该事件对象第一个被调用)
	 * @param {*} signal 标志
	 * @param {*} func 回调
	 * @param {*} self 自己
	 */
	bindPriority: function (signal, func, self) {
		if (!this._callStacks[signal]) {
			this._callStacks[signal] = [];
		}
		this._callStacks[signal].splice(0, 0, { func: func, self: self, once: false });
	},

	/**
	 * 绑定一次(该事件对象在调用之后销毁)
	 * @param {*} signal 标志
	 * @param {*} func 回调
	 * @param {*} self 自己
	 */
	bindOnce: function (signal, func, self) {
		if (!this._callStacks[signal]) {
			this._callStacks[signal] = [];
		}
		this._callStacks[signal].push({ func: func, self: self, once: true });
	},

	/**
	 * 优先绑定一次(该事件对象第一个被调用,且调用之后销毁)
	 * @param {*} signal 标志
	 * @param {*} func 回调
	 * @param {*} self 自己
	 */
	bindOncePriority: function (signal, func, self) {
		if (!this._callStacks[signal]) {
			this._callStacks[signal] = [];
		}
		this._callStacks[signal].splice(0, 0, { func: func, self: self, once: true });
	},

	/**
	 * 解除绑定(事件对象)
	 * @param {*} signal 标志
	 * @param {*} func 回调
	 * @param {*} self 自己
	 * @returns
	 */
	unbind: function (signal, func, self) {
		if (!this._callStacks[signal]) {
			return;
		}
		for (var i = 0; i < this._callStacks[signal].length; i++) {
			if (this._callStacks[signal][i].func === func && (!self || this._callStacks[signal][i].self === self)) {
				this._callStacks[signal].splice(i, 1);
				return;
			}
		}

		if (this._callStacks[signal].length <= 0) {
			this._callStacks[signal] = undefined;
		}
	},

	/**
	 * 销毁
	 * @param {*} signal 标志
	 */
	destroy: function (signal) {
		this._callStacks[signal] = undefined;
	},

	/**
	 * 调用
	 * @param {*} signal 标志
	 * @param {*} data 数据
	 * @returns
	 */
	call: function (signal, data) {
		if (this.debugMode) {
			if (!this.logger) {
				this.logger = console.log;
			}
			this.logger('CALL: ' + signal, data);
		}
		if (this.lastEvent) {
			this.lastEvent.signal = signal;
			this.lastEvent.data = data;
		} else {
			this.lastEvent = { signal: signal, data: data };
		}

		if (!this._callStacks[signal]) {
			return;
		}
		var eves = this._callStacks[signal];
		for (var i = 0; i < eves.length; i++) {
			if (eves[i].func) {
				eves[i].func.call(eves[i].self, data);
				if (eves[i]) {
					eves[i]._processed = true;
				}
			}
			if (eves[i].once) {
				eves.splice(i, 1);
				i--;
			}
		}

		if (eves.length <= 0) {
			this.destroy(signal);
		}
	},
};

whevent.on = whevent.bind;
whevent.onOnce = whevent.bindOnce;
whevent.onPriority = whevent.bindPriority;
whevent.onOncePriority = whevent.bindOncePriority;
whevent.off = whevent.unbind;
whevent.emit = whevent.call;

if (typeof module !== 'undefined') {
	module.exports = whevent;
}
